#ifndef FriendStation_H
#define FriendStation_H

#include <stdio.h>
#include "boolean.h"
#include "senar.h"
#include "mesinkata.h"

/* ADT Social Network Graph yang direpresentasikan sebagai List to User Address (Edge List) */
 
#define nil NULL
 
typedef struct {
    char *Email, Nama, TglLahir, KotaAsal, Universitas, SMU;
} InfoUser;
 
typedef struct {
    Uaddress UFirst;
} MemberList;
typedef tMemberList *Uaddress;
typedef struct tMemberList {
    InfoUser Info;
    Uaddress Next;
    FriendList Friends;
} MemberList;
 
//User's Friends
typedef struct {
    Faddress FFirst;
} FriendList;

typedef tFriendList *Faddress;
typedef struct tFriendList {
    address Info;
    Faddress NextFriends;
} FriendList;
 
 
//Selektor
#define First(L) ((L).First)
#define NextUser(P) (P)-> Next
#define NextFriends(P) (P)-> NextFriends
#define InfoEmail(P) ((P)->Info).Email
#define InfoNama(P) ((P)->Info).Nama
#define InfoTglLahir(P) ((P)->Info).TglLahir
#define InfoKotaAsal(P) ((P)->Info).KotaAsal
#define InfoUniv(P) ((P)->Info).Universitas
#define InfoSMU(P) ((P)->Info).SMU

 
/**** Modus Administrator ****/
void CreateMemberList (MemberList *L);
/*    I.S. sembarang
    F.S. Terbentuk list L kosong */
 
void CreateFriendList (FriendList *F);
/*    I.S. sembarang
    F.S terbentuk list F kosong */
 
boolean IsEmptyMemberList (MemberList *L);
/* I.S sembarang
	Mengembalikan nilai true jika MemberList kosong */

boolean IsEmptyFriendList (FriendList *F);
/* I.S sembarang
	Mengembalikan nilai true jika FriendList kosong */
 
int Load (MemberList *L);
/*    I.S sembarang, list L sudah terbentuk
    F.S file input diloading ke dalam struktur-struktur internal yang dibutuhkan oleh sistem (membentuk struktur graf berarah dari para pengguna sesuai dengan isi         file input */
 
void Save (char *FileInput, MemberList *L);
/*    I.S sembarang
    F.S Kondisi terakhir dari jejaring sosial dituliskan pada file tersebut.
    Jika file adalah file baru, maka harus di-create terlebih dahulu
    Jika file berbeda dari file yang digunakan pada saat load, makan file input load tetap
    Jika argumen Save tidak diberikan, maka secara default, kondisi terakhir pada file input yang digunakan pada saat load terakhir */
 
address Alokasi (InfoUser ID);
/* Mengirimkan address hasil alokasi sebuah elemen */
/* Jika alokasi berhasil, maka address tidak nil, dan misalnya menghasilkan P */
/* Jika alokasi gagal, mengirimkan Nil */

void Dealokasi (address P);
/* I.S. P terdefinisi */
/* F.S. P dikembalikan ke sistem */
/* Melakukan dealokasi/pengembalian address P */
 
void AddUser (MemberList *U, InfoUser ID);
/*     I.S email USER belum terdefinisi di U. U mungkin kosong.
    F.S Insert USER sebagai elemen terakhir dari U dengan urut membesar berdasarkan Nama
    AddUser menggunakan procedure InsSort (menyisipkan user baru dengan terurut membesar berdasarkan nama)    
*/
 
void ModifyUser (MemberList *U, char *E);
/*    I.S P terdefinisi di U
    F.S Data pribadi dari user yang beralamat email E diubah.
    Data pribadi yang diubah antara lain : nama, tanggal lahir, kota asal, universitas, dan SMU
    EMAIL TIDAK DIUBAH
    Bila nama diubah, urutan user di MemberList diurutkan lagi berdasarkan nama    
*/
 
void DelUser (MemberList *U, char *E);
/*  I.S E terdefinisi di U
    F.S Data pribadi (nama, tanggal lahir, kota asal, universitas, SMU) dari pengguna yang beralamat-email E dihapus.
    Perintah ini harus menjamin integrity dari seluruh data (seperti friend relations) */
 
void List (MemberList *U, char *Field, char *state);
/*    I.S U tidak kosong
    F.S isi U ditampilkan sesuai state (asc/desc) berdasarkan Field tertentu (email/nama/tgl lahir/kota asal/universitas/SMU)
    Secara default, List akan ditampilakn daftar semua pengguna terurut asc berdasarkan Nama.
    Keterangan : asc : menampilkan data dalam keadaan terurut membesar
               desc: menampilkan data dalam keadaan terurut mengecil */

			   
/**** Modus Pengguna ****/
address AlokasiF (Info ID);
/* Mengirimkan address hasil alokasi sebuah elemen */
/* Jika alokasi berhasil, maka address tidak nil, dan misalnya menghasilkan P */
/* Jika alokasi gagal, mengirimkan Nil */
 
address SearchFriend (MemberList *U,char *UserId);
/* mengembalikan alamat dari UserId di dalam MemberList */ 
 
void Friend (MemberList *L, FriendList *F, char *UserId);
/*    I.S UserId bisa kosong, atau berisi email orang lain
    F.S Jika UserId kosong : tampilkan semua 1st friend dari CurrentUser
        Jika UserId berisi alamat email orang lain, pengguna dengan UserId tersebut ditambahkan sebagai 1st friend dari CurrentUser
*/
 
void UnFriend (FriendList *F, char *UserId);
/*    I.S UserId tidak kosong dan merupakan 1st friend dari CurrentUser
    F.S Hubungan pertemanan antara CurrentUser dan UserId dihapus
*/

void Birthday (FriendList *L, char *CurrentUser, int day);
/*    I.S    CurrentUser dan day terdefinisi
    F.S    menampilakn list dari 1st friend dari CurrentUser yang berulang tahun dalam jangka waktu Day yang didefinisikan     
        Bila hubungan pertemanan bukan 2 arah, tanggal lahir dari 1st friend tersebut harus di-masking
*/
 
void Same (FriendList *L, char *CurrentUser, char *state);
/*    I.S
    F.S menampilkan list dari 1st, 2nd, 3rd friend yang memiliki sekolah (Universitas/SMU) atau kota asal yang sama dengan current user */
 
void notfriendyet (MemberList *L, char *CurrentUser);
/*    I.S sembarang
    F.S menampilkan list dari 2nd friend dan 3rd friend yang belum menjadi 1st friend dari current user */
 

 /*** Fungsi Antara ***/
boolean IsFound (MemberList *L, char *field, char *S);
/*    I.S    S, field, dan L terdefinisi
    Field adalah Email/Nama/TglLahir/KotaAsal/Universitas/SMU
    F.S    mengembalikan true jika S ditemukan pada L
    (note : bila field adalah Nama, S berisi Joko, Ina, dll [misal])
*/
 
void FirstFriend (MemberList *L, char *CurrentUser, FriendList *F1);
// I.S CurrentUser terdefinisi di dalam L
// F.S 1st friend dari CurrentUser dimasukkan ke variabel F1
 
void SecondFriend (MemberList *L, char *CurrentUser, FriendList *F2);
// I.S CurrentUser terdefinisi di dalam L
// F.S 2nd friend dari CurrentUser dimasukkan ke variabel F2
// 2nd friend adalah teman dari 1st friend yang belum menjadi teman CurrentUser
 
void ThirdFriend (MemberList *L, char *CurrentUser, FriendList *F3);
// I.S CurrentUser terdefinisi di dalam L
// F.S 3rd friend dari CurrentUser dimasukkan ke variabel F3
// 3rd friend adalah teman dari 2nd friend yang belum menjadi teman CurrentUser

void Ignore ();
// I.S command siap menerima input
// F.S program siap menerima command selanjutnya
// menangani command tanpa input
 
#endif
